﻿using System.ComponentModel;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using System.Linq;
using System.Waf.Applications;
using System.Waf.Applications.Services;
using HighLandirect.Applications.Properties;
using HighLandirect.Applications.Services;
using HighLandirect.Applications.ViewModels;
using HighLandirect.Applications.Views;
using HighLandirect.Domain;
using System.Text.RegularExpressions;
using HighLandirect.Foundation;
using System.Collections.Generic;
using HighLandirect.Domain.Reports;
using System.Printing;

namespace HighLandirect.Applications.Controllers
{
    [Export]
    public class CustomerController : Controller
    {
        private readonly IQuestionService questionService;
        private readonly CompositionContainer container;
        private readonly IEntityService entityService;
        private readonly ShellViewModel shellViewModel;
        private readonly CustomerViewModel customerViewModel;
        private CustomerListViewModel customerListViewModel;
        private readonly DelegateCommand searchCommand;
        private readonly DelegateCommand addResceiveCustomerCommand;
        private readonly DelegateCommand addSendCustomerCommand;
        private readonly DelegateCommand addNewCommand;
        private readonly DelegateCommand removeCommand;
        private readonly DelegateCommand printAtenaSealCommand;
        private readonly DelegateCommand printKokyakuDaichoCommand;

        static bool IsHiragana(string str)
        {
            return Regex.IsMatch(str, @"^\p{IsHiragana}*$");
        }
        
        private OrderController orderController;

        [ImportingConstructor]
        public CustomerController(CompositionContainer container, IEntityService entityService, ShellViewModel shellViewModel,
            CustomerViewModel customerViewModel, IQuestionService questionService)
        {
            this.container = container;
            this.entityService = entityService;
            this.shellViewModel = shellViewModel;
            this.customerViewModel = customerViewModel;
            this.addNewCommand = new DelegateCommand(AddNewCustomer, CanAddCustomer);
            this.removeCommand = new DelegateCommand(RemoveCustomer, CanRemoveCustomer);
            this.searchCommand = new DelegateCommand(SearchCustomer, CanSearchCustomer);
            this.addResceiveCustomerCommand = new DelegateCommand(AddResceiveCustomer, CanAddResceiveCustomer);
            this.addSendCustomerCommand = new DelegateCommand(AddSendCustomer, CanAddSendCustomer);
            this.printAtenaSealCommand = new DelegateCommand(PrintAtenaSeal, CanPrintAtenaSeal);
            this.printKokyakuDaichoCommand = new DelegateCommand(PrintKokyakuDaicho, CanPrintKokyakuDaicho);
            this.questionService = questionService;
        }


        public void Initialize(OrderController orderController)
        {
            customerViewModel.PropertyChanged += CustomerViewModelPropertyChanged;
            
            ICustomerListView customerListView = container.GetExportedValue<ICustomerListView>();
            customerListViewModel = new CustomerListViewModel(customerListView, entityService.Customers);
            customerListViewModel.AddNewCommand = addNewCommand;
            customerListViewModel.RemoveCommand = removeCommand;
            customerListViewModel.SearchCommand = searchCommand;
            customerListViewModel.AddResceiveCustomerCommand = addResceiveCustomerCommand;
            customerListViewModel.AddSendCustomerCommand = addSendCustomerCommand;
            customerListViewModel.PrintAtenaSealCommand = printAtenaSealCommand;
            customerListViewModel.PrintKokyakuDaichoCommand = printKokyakuDaichoCommand;

            customerListViewModel.PropertyChanged += CustomerListViewModelPropertyChanged;

            shellViewModel.CustomerListView = customerListViewModel.View;
            shellViewModel.CustomerView = customerViewModel.View;

            customerListViewModel.SelectedCustomer = customerListViewModel.Customers.FirstOrDefault();


            this.orderController = orderController;
        }

        private bool CanAddCustomer() { return customerViewModel.IsValid; }
        private void AddNewCustomer()
        {
            //最大番号プラス1
            int CustNo;
            if (this.entityService.Customers.Count == 0)
            {
                CustNo = 1;
            }
            else
            {
                CustNo = entityService.Customers
                                    .OrderByDescending(x => x.CustNo)
                                    .FirstOrDefault().CustNo + 1;
            }
            Customer customer = new Customer(CustNo);
            customer.Label = false;
            customer.Delete = false;
            entityService.Customers.Add(customer);

            customerListViewModel.SelectedCustomer = customer;
            customerViewModel.Focus();
        }

        private bool CanRemoveCustomer() { return customerListViewModel.SelectedCustomer != null; }
        private void RemoveCustomer()
        {
            foreach (Customer customer in customerListViewModel.SelectedCustomers.ToArray())
            {
                entityService.Customers.Remove(customer);
            }
        }

        private bool CanSearchCustomer() { return true; }
        private void SearchCustomer()
        {
            //とりあえずCustNameでの検索。電話番号、ふりがなでの検索も可能とする

            Customer FoundCustomer;

            FoundCustomer = GetCustomerQuery(this.customerListViewModel.SearchString);
            this.customerListViewModel.SelectedCustomer = FoundCustomer;

            //スクロールバーを移動する
            this.customerListViewModel.ScrollIntoView();
        }

        private Customer GetCustomerQuery(string SearchString)
        {
            Customer FoundCustomer;
            int dummy;
            if (int.TryParse(SearchString.Replace("-", ""), out dummy))
            {
                FoundCustomer = this.entityService.Customers
                            .Where(x => x.Phone.IndexOf(SearchString) >= 0)
                            .FirstOrDefault();
            }
            else if (IsHiragana(this.customerListViewModel.SearchString))
            {
                FoundCustomer = this.entityService.Customers
                            .Where(x => x.Furigana.IndexOf(SearchString) >= 0)
                            .FirstOrDefault();
            }
            else
            {
                FoundCustomer = this.entityService.Customers
                            .Where(x => x.CustName.IndexOf(SearchString) >= 0)
                            .FirstOrDefault();
            }
            return FoundCustomer;
        }

        private void UpdateCommands()
        {
            addNewCommand.RaiseCanExecuteChanged();
            removeCommand.RaiseCanExecuteChanged();
        }

        private void CustomerListViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "SelectedCustomer")
            {
                customerViewModel.Customer = customerListViewModel.SelectedCustomer;
                UpdateCommands();
            }
        }

        private void CustomerViewModelPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == "IsValid")
            {
                UpdateCommands();
            }
        }

        private bool CanAddSendCustomer() { return true; }
        private void AddSendCustomer()
        {
            this.orderController.SendCustNo = this.customerListViewModel.SelectedCustomer.CustNo;
        }

        private bool CanAddResceiveCustomer() { return true; }
        private void AddResceiveCustomer()
        {
            this.orderController.ResceiveCustNo = this.customerListViewModel.SelectedCustomer.CustNo;
        }

        private bool CanPrintAtenaSeal() { return this.customerListViewModel.Customers.Where(x => x.Label == true).Count() > 0; }
        private void PrintAtenaSeal()
        {
            if (this.questionService.ShowYesNoQuestion("宛名ラベルを印刷しますか？"))
            {
                PrintAtenaSealCore();
            }
        }

        private bool CanPrintKokyakuDaicho() { return this.customerListViewModel.Customers.Where(x => x.Label == true).Count() > 0; }
        private void PrintKokyakuDaicho()
        {
            if (this.questionService.ShowYesNoQuestion("顧客台帳を印刷しますか？"))
            {
                PrintKokyakuDaichoCore();
            }
        }

        private void PrintAtenaSealCore()
        {
            LocalPrintServer ps = new LocalPrintServer();
            PrintQueue pq = ps.DefaultPrintQueue; //既定のプリンタ
            //A4縦
            pq.UserPrintTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4);
            pq.UserPrintTicket.PageOrientation = PageOrientation.Portrait;

            var printer = new PrintListReport<Customer, AtenaSeal>(4, pq);
            //ラベル印刷するチェックが入ってる人
            printer.Print(this.customerListViewModel.Customers.Where(x => x.Label == true));
        }

        private void PrintKokyakuDaichoCore()
        {
            LocalPrintServer ps = new LocalPrintServer();
            PrintQueue pq = ps.DefaultPrintQueue; //既定のプリンタ
            //A4縦
            pq.UserPrintTicket.PageMediaSize = new PageMediaSize(PageMediaSizeName.ISOA4);
            pq.UserPrintTicket.PageOrientation = PageOrientation.Portrait;

            var printer = new PrintListReport<Customer, KokyakuDaicho>(10, pq);
            //ラベル印刷するチェックが入ってる人
            printer.Print(this.customerListViewModel.Customers.Where(x => x.Label == true));
        }
    }
}
